﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Epsilon.Parse
{
    public partial class Parser
    {
        public List<Type> ParseTypes()
        {
            List<Type> types = new List<Type>();
            types.Add(ParseType());
            while (MatchPeek(TokenType.Symbol, ","))
            {
                Chomp();
                types.Add(ParseType());
            }
            return types;
        }

        public Type ParseType()
        {
            if (MatchPeek(TokenType.Keyword, "int"))
            {
                Chomp();
                return new SimpleType(BaseType.Int);
            }
            else if (MatchPeek(TokenType.Keyword, "bool"))
            {
                Chomp();
                return new SimpleType(BaseType.Bool);
            }
            else if (MatchPeek(TokenType.Keyword, "string"))
            {
                Chomp();
                return new SimpleType(BaseType.String);
            }
            else if (MatchPeek(TokenType.Keyword, "pid"))
            {
                Chomp();
                return new SimpleType(BaseType.Pid);
            }
            else if (MatchPeek(TokenType.Keyword, "void"))
            {
                Chomp();
                return new SimpleType(BaseType.Unit);
            }
            else if (CheckType(TokenType.Atom))
            {
                AtomType a = new AtomType(CurrentToken().Value);
                Chomp();
                return a;
            }
            else if (MatchPeek(TokenType.Symbol, "["))
            {
                Match(TokenType.Symbol, "[");
                Type type = ParseType();
                Match(TokenType.Symbol, "]");
                return new ListType(type);
            }
            else if (MatchPeek(TokenType.Symbol, "("))
            {
                Match(TokenType.Symbol, "(");
                Type type = ParseType();
                Match(TokenType.Symbol, ")");
                return type;
            }
            else if (MatchPeek(TokenType.Symbol, "{"))
            {
                Match(TokenType.Symbol, "{");
                List<Type> types = ParseTypes();
                Match(TokenType.Symbol, "}");
                return new TupleType(types);
            }
            else if (MatchPeek(TokenType.Keyword, "fun"))
            {
                Match(TokenType.Keyword, "fun");
                Match(TokenType.Symbol, "(");
                List<Type> args = ParseTypes();
                Match(TokenType.Symbol, ")");
                Match(TokenType.Symbol, "->");
                Type ret = ParseType();
                return new FunType(args, ret);
            }
            else
            {
                Error("Invalid type");
            }
            return null;
        }
    }
}
